package top.wshape1.shiziapi.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.wshape1.shiziapi.common.constant.BizCodeEnum;
import top.wshape1.shiziapi.common.constant.RedisConstant;
import top.wshape1.shiziapi.common.exception.CustomException;
import top.wshape1.shiziapi.common.utils.R;
import top.wshape1.shiziapi.project.common.constant.DocumentConstant;
import top.wshape1.shiziapi.project.domain.Project;
import top.wshape1.shiziapi.project.domain.Rtf;
import top.wshape1.shiziapi.project.domain.RtfContent;
import top.wshape1.shiziapi.project.domain.vo.CreateDocVo;
import top.wshape1.shiziapi.project.domain.vo.SaveContentVo;
import top.wshape1.shiziapi.project.domain.vo.TwoIdVo;
import top.wshape1.shiziapi.project.handler.LoginContextHandler;
import top.wshape1.shiziapi.project.mapper.RtfContentMapper;
import top.wshape1.shiziapi.project.mapper.RtfMapper;
import top.wshape1.shiziapi.project.service.ProjectService;
import top.wshape1.shiziapi.project.service.RtfService;
import top.wshape1.shiziapi.project.util.HotProjectUtil;

import java.util.Date;
import java.util.List;

/**
 * @author Wshape1
 * @description 针对表【t_project_rtf】的数据库操作Service实现
 * @since 2023-10-22 18:21:50
 */
@Service
public class RtfServiceImpl extends ServiceImpl<RtfMapper, Rtf>
        implements RtfService {

    @Resource
    private RtfContentMapper rtfContentMapper;

    @Resource
    private ProjectService projectService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Transactional
    @Override
    public Long create(CreateDocVo createDocVo) {

        Rtf rtf = new Rtf();
        rtf.setProjectId(createDocVo.getProjectId());
        rtf.setName(createDocVo.getName());
        rtf.setParentFolderId(createDocVo.getParentFolderId());
        rtf.setOrder(createDocVo.getOrder());
        rtf.setCreateTime(new Date());

        this.save(rtf);

        RtfContent rtfContent = new RtfContent();
        rtfContent.setId(rtf.getId());
        rtfContentMapper.insert(rtfContent);

        return rtf.getId();
    }

    @Override
    public void rename(Long id, String name) {
        this.update(new LambdaUpdateWrapper<Rtf>()
                .eq(Rtf::getId, id)
                .set(Rtf::getName, name));
    }

    @Transactional
    @Override
    public void delete(Long id) {

        rtfContentMapper.deleteById(id);

        this.removeById(id);

    }

    @Transactional
    @Override
    public void deleteByParentFolderId(Long parentFolderId) {
        List<Long> ids = this.getIdsByParentFolderId(parentFolderId);

        if (ids != null && !ids.isEmpty())
            rtfContentMapper.deleteBatchIds(ids);

        this.remove(new LambdaQueryWrapper<Rtf>()
                .eq(Rtf::getParentFolderId, parentFolderId));
    }

    @Override
    public List<Long> getIdsByParentFolderId(Long parentFolderId) {
        return this.getBaseMapper().selectIdsByParentFolderId(parentFolderId);
    }

    @Override
    public void updateOrderAndParentFolderId(Long id, Integer order, Long parentFolderId) {
        this.update(new LambdaUpdateWrapper<Rtf>()
                .eq(Rtf::getId, id)
                .set(Rtf::getOrder, order)
                .set(Rtf::getParentFolderId, parentFolderId)
        );
    }

    @Override
    public void updateOrder(Long id, Integer order) {
        this.update(new LambdaUpdateWrapper<Rtf>()
                .eq(Rtf::getId, id)
                .set(Rtf::getOrder, order)
        );
    }

    @Override
    public String getContent(TwoIdVo contentVo, Long userId) {

        // 先查询是否是热点项目
        Object o = redisTemplate.opsForHash().get(RedisConstant.PROJECT_HOT_KEY + contentVo.getProjectId(),
                RedisConstant.PROJECT_HOT_RTF_KEY + contentVo.getId());
        if (o != null) {
            return (String) o;
        }

        Project project = projectService.getById(contentVo.getProjectId());
        if (project.getIsPrivate() == 1) {
            if (userId == null || !projectService.hasPermissionToEdit(contentVo.getProjectId(), userId))
                throw new CustomException(R.instance(BizCodeEnum.PROJECT_PERMISSION_ERROR));
        }

        RtfContent rtfContent = rtfContentMapper.selectById(contentVo.getId());

        return rtfContent.getContent();
    }

    @Override
    public void SaveContent(SaveContentVo contentVo, Long userId) {

        Object editObj = redisTemplate.opsForValue().get("startEdit:" + contentVo.getProjectId() + ":" + DocumentConstant.RTF_TYPE + ":" + contentVo.getId());
        if (editObj == null || !editObj.toString().equals(String.valueOf(LoginContextHandler.getUserId()))) {
            throw new CustomException(R.instance(BizCodeEnum.DOC_NOT_IN_EDIT_ERROR));
        }

        if (!projectService.hasPermissionToEdit(contentVo.getProjectId(), userId)) {
            throw new CustomException(R.instance(BizCodeEnum.PROJECT_PERMISSION_ERROR));
        }

        int i = rtfContentMapper.updateById(new RtfContent(contentVo.getId(), contentVo.getContent()));

        // 更新热点项目缓存
        if (i > 0) {
            HotProjectUtil.updateCacheIfHot(redisTemplate, contentVo.getProjectId(),
                    RedisConstant.PROJECT_HOT_RTF_KEY + contentVo.getId(), contentVo.getContent());
        }

    }

    @Transactional
    @Override
    public void clearProject(long projectId) {
        List<Long> rtfIds = this.getIdsByProjectId(projectId);

        if (rtfIds != null && !rtfIds.isEmpty()) {
            rtfContentMapper.delete(new LambdaQueryWrapper<RtfContent>()
                    .in(RtfContent::getId, rtfIds));

            this.remove(new LambdaQueryWrapper<Rtf>()
                    .eq(Rtf::getProjectId, projectId));
        }

    }

    public List<Long> getIdsByProjectId(long projectId) {
        return this.getBaseMapper().getIdsByProjectId(projectId);
    }
}





